package com.zhiwen.config;

import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;

import java.util.concurrent.Executor;
import java.util.concurrent.ThreadPoolExecutor;

/**
 * 异步任务配置类
 */
@Configuration
@EnableAsync
public class AsyncConfig {

    /**
     * 配置通知任务线程池
     */
    @Bean("notificationTaskExecutor")
    public Executor notificationTaskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 核心线程数
        executor.setCorePoolSize(5);
        // 最大线程数
        executor.setMaxPoolSize(20);
        // 队列容量
        executor.setQueueCapacity(100);
        // 线程名前缀
        executor.setThreadNamePrefix("notification-");
        // 拒绝策略：使用调用者所在的线程来运行任务
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        // 等待所有任务结束后再关闭线程池
        executor.setWaitForTasksToCompleteOnShutdown(true);
        // 等待时间
        executor.setAwaitTerminationSeconds(60);
        // 初始化
        executor.initialize();
        return executor;
    }

    /**
     * 配置仪表盘数据获取任务线程池
     */
    @Bean("dashboardTaskExecutor") // 新的Bean名称
    public Executor dashboardTaskExecutor() {
        ThreadPoolTaskExecutor executor = new ThreadPoolTaskExecutor();
        // 针对仪表盘数据获取任务的特性进行配置：
        // 通常是I/O密集型，可以适当增加核心线程数以处理并发I/O等待
        // 但也要考虑下游服务的并发承受能力

        // 假设仪表盘并发查询数较多，但每个查询本身不是特别耗CPU
        int corePoolSize = 10; // 核心线程数，可以根据并发查询的数量和服务器CPU核心数调整
        int maxPoolSize = 50;  // 最大线程数，应对峰值情况
        int queueCapacity = 200; // 队列容量，缓冲等待执行的任务

        executor.setCorePoolSize(corePoolSize);
        executor.setMaxPoolSize(maxPoolSize);
        executor.setQueueCapacity(queueCapacity);
        executor.setThreadNamePrefix("dashboard-data-"); // 清晰的线程名前缀
        // 拒绝策略：可以根据业务需求选择。
        // CallerRunsPolicy: 提交任务的线程（在这里可能是处理HTTP请求的Web服务器线程）自己执行，可以起到一定的限流作用。
        // AbortPolicy: 抛出异常，调用方需要处理。
        // DiscardPolicy: 直接丢弃。
        // DiscardOldestPolicy: 丢弃队列中最旧的。
        // 对于仪表盘，如果并发过高，让请求线程自己执行可能导致其响应变慢，但能保证数据获取。
        // 或者，如果允许在极端情况下仪表盘数据加载失败，可以选择抛异常或记录日志后返回错误。
        executor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy()); // 示例，根据实际情况选择
        executor.setWaitForTasksToCompleteOnShutdown(true);
        executor.setAwaitTerminationSeconds(60);
        executor.initialize();
        return executor;
    }

}
